package com.example.task.config.schedule;

import com.example.task.dao.ScheduleConfigDao;
import com.example.task.entity.ScheduleConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.ReflectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

/**
 * @author sunny
 */
@Slf4j
@Configuration
@EnableScheduling
public class SchedulingConfig implements SchedulingConfigurer {

    @Resource
    private ScheduleConfigDao scheduleConfigDao;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        // 获取所有任务
        List<ScheduleConfig> scheduleList = scheduleConfigDao.getScheduleList();
        log.info("定时器数量" + scheduleList.size());
        for (ScheduleConfig s : scheduleList) {
            scheduledTaskRegistrar.addTriggerTask(getRunnable(s), getTrigger(s));
        }
    }


    /**
     * 转换首字母小写
     */
    public static String lowerFirstCapse(String str) {
        char[] chars = str.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

    /**
     * runnable
     */
    private Runnable getRunnable(ScheduleConfig scheduleConfig) {
        return () -> {
            Class<?> clazz;
            try {
                clazz = Class.forName(scheduleConfig.getClassName());
                String className = lowerFirstCapse(clazz.getSimpleName());
                Object bean = SpringContextHolder.getBean(className);
                Method method = ReflectionUtils.findMethod(bean.getClass(), scheduleConfig.getMethod());
                ReflectionUtils.invokeMethod(method, bean);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        };
    }

    /**
     * Trigger
     */
    private Trigger getTrigger(ScheduleConfig scheduleConfig) {
        String id = scheduleConfig.getId();
        return new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                //任务触发，可修改任务的执行周期.
                //每一次任务触发，都会执行这里的方法一次，重新获取下一次的执行时间
                ScheduleConfig scheduleOne = scheduleConfigDao.findOne(id);
                CronTrigger trigger = new CronTrigger(scheduleOne.getCron());
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        };

    }
}
